home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / PixelMotionBlur / PixelMotionBlur.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  56.4 KB  |  1,298 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: PixelMotionBlur.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10.  
  11. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  12. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  13.  
  14.  
  15. //-----------------------------------------------------------------------------
  16. // Globals variables and definitions
  17. //-----------------------------------------------------------------------------
  18. #define NUM_OBJECTS 40
  19. #define NUM_WALLS 250
  20. #define MOVESTYLE_DEFAULT 0
  21.  
  22. struct SCREEN_VERTEX 
  23. {
  24.     D3DXVECTOR4 pos;
  25.     DWORD       clr;
  26.     D3DXVECTOR2 tex1;
  27.  
  28.     static const DWORD FVF;
  29. };
  30. const DWORD SCREEN_VERTEX::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1;
  31.  
  32.  
  33. struct OBJECT
  34. {
  35.     D3DXVECTOR3         g_vWorldPos;       
  36.     D3DXMATRIXA16       g_mWorld;
  37.     D3DXMATRIXA16       g_mWorldLast;
  38.     LPD3DXMESH          g_pMesh;
  39.     LPDIRECT3DTEXTURE9  g_pMeshTexture;
  40. };
  41.  
  42.  
  43. struct CRenderTargetSet
  44. {
  45.     IDirect3DSurface9* pRT[2][2];  // Two passes, two RTs
  46. };
  47.  
  48.  
  49. //--------------------------------------------------------------------------------------
  50. // Global variables
  51. //--------------------------------------------------------------------------------------
  52. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  53. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  54. ID3DXEffect*            g_pEffect = NULL;       // D3DX effect interface
  55. D3DFORMAT               g_VelocityTexFormat;    // Texture format for velocity textures
  56. CFirstPersonCamera      g_Camera;               
  57. bool                    g_bShowHelp = true;     // If true, it renders the UI control text
  58. CDXUTDialog             g_HUD;                  // dialog for standard controls
  59. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  60.  
  61. SCREEN_VERTEX           g_Vertex[4];
  62.  
  63. LPD3DXMESH              g_pMesh1;
  64. LPDIRECT3DTEXTURE9      g_pMeshTexture1;
  65. LPD3DXMESH              g_pMesh2;
  66. LPDIRECT3DTEXTURE9      g_pMeshTexture2;
  67. LPDIRECT3DTEXTURE9      g_pMeshTexture3;
  68.  
  69. LPDIRECT3DTEXTURE9      g_pFullScreenRenderTarget;
  70. LPDIRECT3DSURFACE9      g_pFullScreenRenderTargetSurf;
  71.  
  72. LPDIRECT3DTEXTURE9      g_pPixelVelocityTexture1;
  73. LPDIRECT3DSURFACE9      g_pPixelVelocitySurf1;
  74. LPDIRECT3DTEXTURE9      g_pPixelVelocityTexture2;
  75. LPDIRECT3DSURFACE9      g_pPixelVelocitySurf2;
  76.  
  77. LPDIRECT3DTEXTURE9      g_pLastFrameVelocityTexture;
  78. LPDIRECT3DSURFACE9      g_pLastFrameVelocitySurf;
  79. LPDIRECT3DTEXTURE9      g_pCurFrameVelocityTexture;
  80. LPDIRECT3DSURFACE9      g_pCurFrameVelocitySurf;
  81.  
  82. FLOAT                   g_fChangeTime;
  83. bool                    g_bShowBlurFactor;
  84. bool                    g_bShowUnblurred;
  85. DWORD                   g_dwBackgroundColor;
  86.  
  87. float                   g_fPixelBlurConst;
  88. float                   g_fObjectSpeed;
  89. float                   g_fCameraSpeed;
  90.  
  91. OBJECT*                 g_pScene1Object[NUM_OBJECTS];
  92. OBJECT*                 g_pScene2Object[NUM_WALLS];
  93. DWORD                   g_dwMoveSytle;
  94. int                     g_nSleepTime;
  95. D3DXMATRIX              g_mViewProjectionLast;
  96. int                     g_nCurrentScene;
  97.  
  98. D3DXHANDLE              g_hWorld;
  99. D3DXHANDLE              g_hWorldLast;
  100. D3DXHANDLE              g_hMeshTexture;
  101. D3DXHANDLE              g_hWorldViewProjection;
  102. D3DXHANDLE              g_hWorldViewProjectionLast;
  103. D3DXHANDLE              g_hCurFrameVelocityTexture;
  104. D3DXHANDLE              g_hLastFrameVelocityTexture;
  105. D3DXHANDLE              g_hTechWorldWithVelocity;
  106. D3DXHANDLE              g_hPostProcessMotionBlur;
  107.  
  108. int                     g_nPasses = 0;          // Number of passes required to render
  109. int                     g_nRtUsed = 0;          // Number of render targets used by each pass
  110. CRenderTargetSet        g_aRTSet[2];            // Two sets of render targets
  111. CRenderTargetSet*       g_pCurFrameRTSet;      // Render target set for current frame
  112. CRenderTargetSet*       g_pLastFrameRTSet;     // Render target set for last frame
  113.  
  114.  
  115. //--------------------------------------------------------------------------------------
  116. // UI control IDs
  117. //--------------------------------------------------------------------------------------
  118. #define IDC_TOGGLEFULLSCREEN    1
  119. #define IDC_TOGGLEREF           3
  120. #define IDC_CHANGEDEVICE        4
  121. #define IDC_CHANGE_SCENE        5
  122. #define IDC_ENABLE_BLUR         6
  123. #define IDC_FRAMERATE           7
  124. #define IDC_FRAMERATE_STATIC    8
  125. #define IDC_BLUR_FACTOR         9
  126. #define IDC_BLUR_FACTOR_STATIC  10
  127. #define IDC_OBJECT_SPEED        11
  128. #define IDC_OBJECT_SPEED_STATIC 12
  129. #define IDC_CAMERA_SPEED        13
  130. #define IDC_CAMERA_SPEED_STATIC 14
  131.  
  132.  
  133. //--------------------------------------------------------------------------------------
  134. // Forward declarations 
  135. //--------------------------------------------------------------------------------------
  136. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  137. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  138. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  139. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  140. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  141. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  142. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  143. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  144. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  145. void    CALLBACK OnLostDevice();
  146. void    CALLBACK OnDestroyDevice();
  147.  
  148. void    InitApp();
  149. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  150. void    RenderText();
  151. void    SetupFullscreenQuad( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  152.  
  153.  
  154. //--------------------------------------------------------------------------------------
  155. // Entry point to the program. Initializes everything and goes into a message processing 
  156. // loop. Idle time is used to render the scene.
  157. //--------------------------------------------------------------------------------------
  158. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  159. {
  160.     // Set the callback functions. These functions allow the sample framework to notify
  161.     // the application about device changes, user input, and windows messages.  The 
  162.     // callbacks are optional so you need only set callbacks for events you're interested 
  163.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  164.     // framework won't be able to reset your device since the application must first 
  165.     // release all device resources before resetting.  Likewise, if you don't handle the 
  166.     // device created/destroyed callbacks then the sample framework won't be able to 
  167.     // recreate your device resources.
  168.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  169.     DXUTSetCallbackDeviceReset( OnResetDevice );
  170.     DXUTSetCallbackDeviceLost( OnLostDevice );
  171.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  172.     DXUTSetCallbackMsgProc( MsgProc );
  173.     DXUTSetCallbackKeyboard( KeyboardProc );
  174.     DXUTSetCallbackFrameRender( OnFrameRender );
  175.     DXUTSetCallbackFrameMove( OnFrameMove );
  176.  
  177.     // Show the cursor and clip it when in full screen
  178.     DXUTSetCursorSettings( true, true );
  179.  
  180.     InitApp();
  181.  
  182.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  183.     // device for the application. Calling each of these functions is optional, but they
  184.     // allow you to set several options which control the behavior of the framework.
  185.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  186.     DXUTCreateWindow( L"PixelMotionBlur" );
  187.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  188.  
  189.     // Pass control to the sample framework for handling the message pump and 
  190.     // dispatching render calls. The sample framework will call your FrameMove 
  191.     // and FrameRender callback when there is idle time between handling window messages.
  192.     DXUTMainLoop();
  193.  
  194.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  195.     // appropriate callback functions and therefore don't require any cleanup code here.
  196.     int iObject;
  197.     for( iObject=0; iObject < NUM_OBJECTS; iObject++ )
  198.         SAFE_DELETE( g_pScene1Object[iObject] );
  199.  
  200.     for( iObject=0; iObject < NUM_WALLS; iObject++ )
  201.         SAFE_DELETE( g_pScene2Object[iObject] );
  202.  
  203.     return DXUTGetExitCode();
  204. }
  205.  
  206.  
  207. //--------------------------------------------------------------------------------------
  208. // Initialize the app 
  209. //--------------------------------------------------------------------------------------
  210. void InitApp()
  211. {
  212.     g_pFullScreenRenderTarget = NULL;
  213.     g_pFullScreenRenderTargetSurf = NULL;
  214.     g_pPixelVelocityTexture1 = NULL;
  215.     g_pPixelVelocitySurf1 = NULL;
  216.     g_pPixelVelocityTexture2 = NULL;
  217.     g_pPixelVelocitySurf2 = NULL;
  218.     g_pLastFrameVelocityTexture = NULL;
  219.     g_pCurFrameVelocityTexture = NULL;
  220.     g_pCurFrameVelocitySurf = NULL;
  221.     g_pLastFrameVelocitySurf = NULL;
  222.     g_pEffect = NULL;
  223.     g_nSleepTime = 0;
  224.     g_fPixelBlurConst = 1.0f;
  225.     g_fObjectSpeed = 8.0f;
  226.     g_fCameraSpeed = 20.0f;
  227.     g_nCurrentScene = 1;   
  228.  
  229.     g_fChangeTime = 0.0f;
  230.     g_dwMoveSytle = MOVESTYLE_DEFAULT;
  231.     D3DXMatrixIdentity( &g_mViewProjectionLast );
  232.  
  233.     g_hWorld = NULL;
  234.     g_hWorldLast = NULL;
  235.     g_hMeshTexture = NULL;
  236.     g_hWorldViewProjection = NULL;
  237.     g_hWorldViewProjectionLast = NULL;
  238.     g_hCurFrameVelocityTexture = NULL;
  239.     g_hLastFrameVelocityTexture = NULL;
  240.     g_hTechWorldWithVelocity = NULL;
  241.     g_hPostProcessMotionBlur = NULL;
  242.  
  243.     g_pMesh1 = NULL;
  244.     g_pMeshTexture1 = NULL;
  245.     g_pMesh2 = NULL;
  246.     g_pMeshTexture2 = NULL;
  247.     g_pMeshTexture3 = NULL;
  248.     g_bShowBlurFactor = FALSE;
  249.     g_bShowUnblurred = FALSE;
  250.     g_bShowHelp = TRUE;
  251.     g_dwBackgroundColor = 0x00003F3F;
  252.  
  253.     int iObject;
  254.     for( iObject=0; iObject < NUM_OBJECTS; iObject++ )
  255.     {
  256.         g_pScene1Object[iObject] = new OBJECT;
  257.         ZeroMemory( g_pScene1Object[iObject], sizeof(OBJECT) );
  258.         if( g_pScene1Object[iObject] == NULL )
  259.             return;
  260.     }
  261.  
  262.     for( iObject=0; iObject < NUM_WALLS; iObject++ )
  263.     {
  264.         g_pScene2Object[iObject] = new OBJECT;
  265.         ZeroMemory( g_pScene2Object[iObject], sizeof(OBJECT) );
  266.         if( g_pScene2Object[iObject] == NULL )
  267.             return;
  268.     }
  269.  
  270.     // Initialize dialogs
  271.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  272.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  273.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  274.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  275.  
  276.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; 
  277.     g_SampleUI.AddButton( IDC_CHANGE_SCENE, L"Change Scene", 35, iY += 24, 125, 22 );
  278.     g_SampleUI.AddCheckBox( IDC_ENABLE_BLUR, L"Enable Blur", 35, iY += 24, 125, 22, true );
  279.  
  280.     WCHAR sz[100];
  281.     iY += 10;
  282.     _snwprintf( sz, 100, L"Sleep: %dms/frame", g_nSleepTime ); sz[99] = 0;
  283.     g_SampleUI.AddStatic( IDC_FRAMERATE_STATIC, sz, 35, iY += 24, 125, 22 );
  284.     g_SampleUI.AddSlider( IDC_FRAMERATE, 50, iY += 24, 100, 22, 0, 100, g_nSleepTime );
  285.  
  286.     iY += 10;
  287.     _snwprintf( sz, 100, L"Blur Factor: %0.2f", g_fPixelBlurConst ); sz[99] = 0;
  288.     g_SampleUI.AddStatic( IDC_BLUR_FACTOR_STATIC, sz, 35, iY += 24, 125, 22 );
  289.     g_SampleUI.AddSlider( IDC_BLUR_FACTOR, 50, iY += 24, 100, 22, 1, 200, (int) (g_fPixelBlurConst*100.0f) );
  290.  
  291.     iY += 10;
  292.     _snwprintf( sz, 100, L"Object Speed: %0.2f", g_fObjectSpeed ); sz[99] = 0;
  293.     g_SampleUI.AddStatic( IDC_OBJECT_SPEED_STATIC, sz, 35, iY += 24, 125, 22 );
  294.     g_SampleUI.AddSlider( IDC_OBJECT_SPEED, 50, iY += 24, 100, 22, 0, 30, (int)g_fObjectSpeed );
  295.  
  296.     iY += 10;
  297.     _snwprintf( sz, 100, L"Camera Speed: %0.2f", g_fCameraSpeed ); sz[99] = 0;
  298.     g_SampleUI.AddStatic( IDC_CAMERA_SPEED_STATIC, sz, 35, iY += 24, 125, 22 );
  299.     g_SampleUI.AddSlider( IDC_CAMERA_SPEED, 50, iY += 24, 100, 22, 0, 100, (int)g_fCameraSpeed  );
  300. }
  301.  
  302.  
  303. //--------------------------------------------------------------------------------------
  304. // Called during device initialization, this code checks the device for some 
  305. // minimum set of capabilities, and rejects those that don't pass by returning false.
  306. //--------------------------------------------------------------------------------------
  307. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  308.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  309. {
  310.     // Skip backbuffer formats that don't support alpha blending
  311.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  312.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  313.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  314.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  315.         return false;
  316.  
  317.     // No fallback, so need ps2.0
  318.     if( pCaps->PixelShaderVersion < D3DPS_VERSION(2,0) )
  319.         return false;
  320.  
  321.     // No fallback, so need to support render target
  322.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  323.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  324.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  325.     {
  326.         return false;
  327.     }
  328.  
  329.     // No fallback, so need to support D3DFMT_G16R16F or D3DFMT_A16B16G16R16F render target
  330.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  331.                     AdapterFormat, D3DUSAGE_RENDERTARGET, 
  332.                     D3DRTYPE_TEXTURE, D3DFMT_G16R16F ) ) )
  333.     {
  334.         if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  335.                         AdapterFormat, D3DUSAGE_RENDERTARGET, 
  336.                         D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F ) ) )
  337.         {
  338.             return false;
  339.         }
  340.     }
  341.  
  342.     return true;
  343. }
  344.  
  345.  
  346. //--------------------------------------------------------------------------------------
  347. // This callback function is called immediately before a device is created to allow the 
  348. // application to modify the device settings. The supplied pDeviceSettings parameter 
  349. // contains the settings that the framework has selected for the new device, and the 
  350. // application can make any desired changes directly to this structure.  Note however that 
  351. // the sample framework will not correct invalid device settings so care must be taken 
  352. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  353. //--------------------------------------------------------------------------------------
  354. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  355. {
  356.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  357.     // then switch to SWVP.
  358.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  359.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  360.     {
  361.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  362.     }
  363.     else
  364.     {
  365.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  366.     }
  367.  
  368.     // This application is designed to work on a pure device by not using 
  369.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  370.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  371.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  372.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  373.  
  374.     // Debugging vertex shaders requires either REF or software vertex processing 
  375.     // and debugging pixel shaders requires REF.  
  376. #ifdef DEBUG_VS
  377.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  378.     {
  379.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  380.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  381.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  382.     }
  383. #endif
  384. #ifdef DEBUG_PS
  385.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  386. #endif
  387. }
  388.  
  389.  
  390. //--------------------------------------------------------------------------------------
  391. // This callback function will be called immediately after the Direct3D device has been 
  392. // created, which will happen during application initialization and windowed/full screen 
  393. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  394. // resources need to be reloaded whenever the device is destroyed. Resources created  
  395. // here should be released in the OnDestroyDevice callback. 
  396. //--------------------------------------------------------------------------------------
  397. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  398. {
  399.     HRESULT hr;
  400.  
  401.     // Query multiple RT setting and set the num of passes required
  402.     D3DCAPS9 Caps;
  403.     pd3dDevice->GetDeviceCaps( &Caps );
  404.     if( Caps.NumSimultaneousRTs < 2 )
  405.     {
  406.         g_nPasses = 2;
  407.         g_nRtUsed = 1;
  408.     }
  409.     else
  410.     {
  411.         g_nPasses = 1;
  412.         g_nRtUsed = 2;
  413.     }
  414.  
  415.     // Determine which of D3DFMT_G16R16F or D3DFMT_A16B16G16R16F to use for velocity texture
  416.     IDirect3D9* pD3D;
  417.     pd3dDevice->GetDirect3D( &pD3D );
  418.     D3DDISPLAYMODE DisplayMode;
  419.     pd3dDevice->GetDisplayMode( 0, &DisplayMode );
  420.  
  421.     if( FAILED( pD3D->CheckDeviceFormat( Caps.AdapterOrdinal, Caps.DeviceType,
  422.                     DisplayMode.Format, D3DUSAGE_RENDERTARGET, 
  423.                     D3DRTYPE_TEXTURE, D3DFMT_G16R16F ) ) )
  424.         g_VelocityTexFormat = D3DFMT_A16B16G16R16F;
  425.     else
  426.         g_VelocityTexFormat = D3DFMT_G16R16F;
  427.  
  428.     SAFE_RELEASE( pD3D );
  429.  
  430.     // Initialize the font
  431.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  432.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  433.                          L"Arial", &g_pFont ) );
  434.  
  435.     V_RETURN( LoadMesh( pd3dDevice, L"misc\\sphere.x", &g_pMesh1 ) );
  436.     V_RETURN( LoadMesh( pd3dDevice, L"quad.x", &g_pMesh2 ) );
  437.  
  438.     // Create the mesh texture from a file
  439.     WCHAR str[MAX_PATH];
  440.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"earth\\earth.bmp" ) );
  441.     V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, str, &g_pMeshTexture1 ) );
  442.  
  443.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"misc\\env2.bmp" ) );
  444.     V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, str, &g_pMeshTexture2 ) );
  445.  
  446.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"misc\\seafloor.bmp" ) );
  447.     V_RETURN( D3DXCreateTextureFromFile( pd3dDevice, str, &g_pMeshTexture3 ) );
  448.  
  449.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  450.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  451.     // processing, and debugging pixel shaders requires REF.  The 
  452.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  453.     // shader debugger.  It enables source level debugging, prevents instruction 
  454.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  455.     // against the next higher available software target, which ensures that the 
  456.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  457.     // flags will cause slower rendering since the shaders will be unoptimized and 
  458.     // forced into software.  See the DirectX documentation for more information about 
  459.     // using the shader debugger.
  460.     DWORD dwShaderFlags = 0;
  461.     #ifdef DEBUG_VS
  462.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  463.     #endif
  464.     #ifdef DEBUG_PS
  465.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  466.     #endif
  467.  
  468.     // Read the D3DX effect file
  469.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"PixelMotionBlur.fx" ) );
  470.  
  471.     // If this fails, there should be debug output as to 
  472.     // they the .fx file failed to compile
  473.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  474.                                         NULL, &g_pEffect, NULL ) );
  475.  
  476.     int iObject;
  477.     for( iObject=0; iObject < NUM_OBJECTS; iObject++ )
  478.     {
  479.         g_pScene1Object[iObject]->g_pMesh = g_pMesh1;
  480.         g_pScene1Object[iObject]->g_pMeshTexture = g_pMeshTexture1;
  481.     }
  482.  
  483.     for( iObject=0; iObject < NUM_WALLS; iObject++ )
  484.     {
  485.         g_pScene2Object[iObject]->g_pMesh = g_pMesh2;
  486.  
  487.         D3DXVECTOR3 vPos;
  488.         D3DXMATRIX mRot;
  489.         D3DXMATRIX mPos;
  490.         D3DXMATRIX mScale;
  491.  
  492.         if( iObject < NUM_WALLS/5*1 )
  493.         {
  494.             g_pScene2Object[iObject]->g_pMeshTexture = g_pMeshTexture3;
  495.  
  496.             // Center floor
  497.             vPos.x = 0.0f;
  498.             vPos.y = 0.0f;
  499.             vPos.z = (iObject-NUM_WALLS/5*0) * 1.0f + 10.0f;
  500.  
  501.             D3DXMatrixRotationX( &mRot, -D3DX_PI/2.0f );
  502.             D3DXMatrixScaling( &mScale, 1.0f, 1.0f, 1.0f );
  503.         }
  504.         else if( iObject < NUM_WALLS/5*2 )
  505.         {
  506.             g_pScene2Object[iObject]->g_pMeshTexture = g_pMeshTexture3;
  507.  
  508.             // Right floor
  509.             vPos.x = 1.0f;
  510.             vPos.y = 0.0f;
  511.             vPos.z = (iObject-NUM_WALLS/5*1) * 1.0f + 10.0f;
  512.  
  513.             D3DXMatrixRotationX( &mRot, -D3DX_PI/2.0f );
  514.             D3DXMatrixScaling( &mScale, 1.0f, 1.0f, 1.0f );
  515.         }
  516.         else if( iObject < NUM_WALLS/5*3 )
  517.         {
  518.             g_pScene2Object[iObject]->g_pMeshTexture = g_pMeshTexture3;
  519.  
  520.             // Left floor
  521.             vPos.x = -1.0f;
  522.             vPos.y = 0.0f;
  523.             vPos.z = (iObject-NUM_WALLS/5*2) * 1.0f + 10.0f;
  524.  
  525.             D3DXMatrixRotationX( &mRot, -D3DX_PI/2.0f );
  526.             D3DXMatrixScaling( &mScale, 1.0f, 1.0f, 1.0f );
  527.         }
  528.         else if( iObject < NUM_WALLS/5*4 )
  529.         {
  530.             g_pScene2Object[iObject]->g_pMeshTexture = g_pMeshTexture2;
  531.  
  532.             // Right wall 
  533.             vPos.x = 1.5f;
  534.             vPos.y = 0.5f;
  535.             vPos.z = (iObject-NUM_WALLS/5*3) * 1.0f + 10.0f;
  536.  
  537.             D3DXMatrixRotationY( &mRot, -D3DX_PI/2.0f );
  538.             D3DXMatrixScaling( &mScale, 1.0f, 1.0f, 1.0f );
  539.         }
  540.         else if( iObject < NUM_WALLS/5*5 )
  541.         {
  542.             g_pScene2Object[iObject]->g_pMeshTexture = g_pMeshTexture2;
  543.  
  544.             // Left wall 
  545.             vPos.x = -1.5f;
  546.             vPos.y = 0.5f;
  547.             vPos.z = (iObject-NUM_WALLS/5*4) * 1.0f + 10.0f;
  548.  
  549.             D3DXMatrixRotationY( &mRot, D3DX_PI/2.0f );
  550.             D3DXMatrixScaling( &mScale, 1.0f, 1.0f, 1.0f );
  551.         }
  552.  
  553.         // Update the current world matrix for this object
  554.         D3DXMatrixTranslation( &mPos, vPos.x, vPos.y, vPos.z );
  555.         g_pScene2Object[iObject]->g_mWorld = mRot * mPos;
  556.         g_pScene2Object[iObject]->g_mWorld = mScale * g_pScene2Object[iObject]->g_mWorld;
  557.  
  558.         // The walls don't move so just copy the current world matrix
  559.         g_pScene2Object[iObject]->g_mWorldLast = g_pScene2Object[iObject]->g_mWorld;
  560.     }
  561.  
  562.     // Setup the camera
  563.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  564.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 1.0f, 1000.0f );
  565.  
  566.     D3DXVECTOR3 vecEye(40.0f, 0.0f, -15.0f);
  567.     D3DXVECTOR3 vecAt (4.0f, 4.0f, -15.0f);
  568.     g_Camera.SetViewParams( &vecEye, &vecAt );
  569.  
  570.     g_Camera.SetScalers( 0.01f, g_fCameraSpeed );
  571.  
  572.     return S_OK;
  573. }
  574.  
  575.  
  576. //--------------------------------------------------------------------------------------
  577. // This function loads the mesh and ensures the mesh has normals; it also optimizes the 
  578. // mesh for the graphics card's vertex cache, which improves performance by organizing 
  579. // the internal triangle list for less cache misses.
  580. //--------------------------------------------------------------------------------------
  581. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh )
  582. {
  583.     ID3DXMesh* pMesh = NULL;
  584.     WCHAR str[MAX_PATH];
  585.     HRESULT hr;
  586.  
  587.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  588.     // sample we'll ignore the X file's embedded materials since we know 
  589.     // exactly the model we're loading.  See the mesh samples such as
  590.     // "OptimizedMesh" for a more generic mesh loading example.
  591.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );
  592.  
  593.     V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) );
  594.  
  595.     DWORD *rgdwAdjacency = NULL;
  596.  
  597.     // Make sure there are normals which are required for lighting
  598.     if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
  599.     {
  600.         ID3DXMesh* pTempMesh;
  601.         V( pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  602.                                   pMesh->GetFVF() | D3DFVF_NORMAL, 
  603.                                   pd3dDevice, &pTempMesh ) );
  604.         V( D3DXComputeNormals( pTempMesh, NULL ) );
  605.  
  606.         SAFE_RELEASE( pMesh );
  607.         pMesh = pTempMesh;
  608.     }
  609.  
  610.     // Optimize the mesh for this graphics card's vertex cache 
  611.     // so when rendering the mesh's triangle list the vertices will 
  612.     // cache hit more often so it won't have to re-execute the vertex shader 
  613.     // on those vertices so it will improve perf.     
  614.     rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
  615.     if( rgdwAdjacency == NULL )
  616.         return E_OUTOFMEMORY;
  617.     V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  618.     V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  619.     delete []rgdwAdjacency;
  620.  
  621.     *ppMesh = pMesh;
  622.  
  623.     return S_OK;
  624. }
  625.  
  626.  
  627. //--------------------------------------------------------------------------------------
  628. // This callback function will be called immediately after the Direct3D device has been 
  629. // reset, which will happen after a lost device scenario. This is the best location to 
  630. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  631. // the device is lost. Resources created here should be released in the OnLostDevice 
  632. // callback. 
  633. //--------------------------------------------------------------------------------------
  634. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  635.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  636. {
  637.     HRESULT hr;
  638.  
  639.     if( g_pFont )
  640.         V_RETURN( g_pFont->OnResetDevice() );
  641.     if( g_pEffect )
  642.         V_RETURN( g_pEffect->OnResetDevice() );
  643.  
  644.     // Create a sprite to help batch calls when drawing many lines of text
  645.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  646.  
  647.     // Setup the camera's projection parameters
  648.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  649.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  650.  
  651.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  652.     g_HUD.SetSize( 170, 170 );
  653.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-350 );
  654.     g_SampleUI.SetSize( 170, 300 );
  655.  
  656.     // Create a A8R8G8B8 render target texture.  This will be used to render 
  657.     // the full screen and then rendered to the backbuffer using a quad.
  658.     V_RETURN( D3DXCreateTexture( pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 
  659.                                  1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 
  660.                                   D3DPOOL_DEFAULT, &g_pFullScreenRenderTarget ) );
  661.  
  662.     // Create two floating-point render targets with at least 2 channels.  These will be used to store 
  663.     // velocity of each pixel (one for the current frame, and one for last frame).
  664.     V_RETURN( D3DXCreateTexture( pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 
  665.                                  1, D3DUSAGE_RENDERTARGET, g_VelocityTexFormat, 
  666.                                  D3DPOOL_DEFAULT, &g_pPixelVelocityTexture1 ) );
  667.     V_RETURN( D3DXCreateTexture( pd3dDevice, pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height, 
  668.                                  1, D3DUSAGE_RENDERTARGET, g_VelocityTexFormat, 
  669.                                  D3DPOOL_DEFAULT, &g_pPixelVelocityTexture2 ) );
  670.  
  671.     // Store pointers to surfaces so we can call SetRenderTarget() later
  672.     V_RETURN( g_pFullScreenRenderTarget->GetSurfaceLevel(0, &g_pFullScreenRenderTargetSurf ) );
  673.     V_RETURN( g_pPixelVelocityTexture1->GetSurfaceLevel(0, &g_pPixelVelocitySurf1 ) );
  674.     V_RETURN( g_pPixelVelocityTexture2->GetSurfaceLevel(0, &g_pPixelVelocitySurf2 ) );
  675.  
  676.     // Setup render target sets
  677.     if( 1 == g_nPasses )
  678.     {
  679.         // Multiple RTs
  680.  
  681.         // First frame
  682.         g_aRTSet[0].pRT[0][0] = g_pFullScreenRenderTargetSurf;
  683.         g_aRTSet[0].pRT[0][1] = g_pPixelVelocitySurf1;
  684.         g_aRTSet[0].pRT[1][0] = NULL;  // 2nd pass is not needed
  685.         g_aRTSet[0].pRT[1][1] = NULL;  // 2nd pass is not needed
  686.  
  687.         // Second frame
  688.         g_aRTSet[1].pRT[0][0] = g_pFullScreenRenderTargetSurf;
  689.         g_aRTSet[1].pRT[0][1] = g_pPixelVelocitySurf2;
  690.         g_aRTSet[1].pRT[1][0] = NULL;  // 2nd pass is not needed
  691.         g_aRTSet[1].pRT[1][1] = NULL;  // 2nd pass is not needed
  692.     }
  693.     else
  694.     {
  695.         // Single RT, multiple passes
  696.  
  697.         // First frame
  698.         g_aRTSet[0].pRT[0][0] = g_pFullScreenRenderTargetSurf;
  699.         g_aRTSet[0].pRT[0][1] = NULL;  // 2nd RT is not needed
  700.         g_aRTSet[0].pRT[1][0] = g_pPixelVelocitySurf1;
  701.         g_aRTSet[0].pRT[1][1] = NULL;  // 2nd RT is not needed
  702.  
  703.         // Second frame
  704.         g_aRTSet[1].pRT[0][0] = g_pFullScreenRenderTargetSurf;
  705.         g_aRTSet[1].pRT[0][1] = NULL;  // 2nd RT is not needed
  706.         g_aRTSet[1].pRT[1][0] = g_pPixelVelocitySurf2;
  707.         g_aRTSet[1].pRT[1][1] = NULL;  // 2nd RT is not needed
  708.     }
  709.  
  710.     // Setup the current & last pointers that are swapped every frame.
  711.     g_pCurFrameVelocityTexture = g_pPixelVelocityTexture1;
  712.     g_pLastFrameVelocityTexture = g_pPixelVelocityTexture2;
  713.     g_pCurFrameVelocitySurf = g_pPixelVelocitySurf1;
  714.     g_pLastFrameVelocitySurf = g_pPixelVelocitySurf2;
  715.     g_pCurFrameRTSet = &g_aRTSet[0];
  716.     g_pLastFrameRTSet = &g_aRTSet[1];
  717.  
  718.     SetupFullscreenQuad( pBackBufferSurfaceDesc );
  719.  
  720.     D3DXCOLOR colorWhite(1.0f, 1.0f, 1.0f, 1.0f);
  721.     D3DXCOLOR colorBlack(0.0f, 0.0f, 0.0f, 1.0f);
  722.     D3DXCOLOR colorAmbient(0.35f, 0.35f, 0.35f, 0);
  723.     D3DXCOLOR colorSpecular(0.5f, 0.5f, 0.5f, 1.0f);
  724.     V_RETURN( g_pEffect->SetVector("MaterialAmbientColor", (D3DXVECTOR4*)&colorAmbient ) );
  725.     V_RETURN( g_pEffect->SetVector("MaterialDiffuseColor", (D3DXVECTOR4*)&colorWhite ) );
  726.     V_RETURN( g_pEffect->SetTexture("RenderTargetTexture", g_pFullScreenRenderTarget ) );
  727.  
  728.     D3DSURFACE_DESC desc;
  729.     V_RETURN( g_pFullScreenRenderTargetSurf->GetDesc(&desc) );
  730.     V_RETURN( g_pEffect->SetFloat("RenderTargetWidth", (FLOAT)desc.Width ) );
  731.     V_RETURN( g_pEffect->SetFloat("RenderTargetHeight", (FLOAT)desc.Height ) );
  732.  
  733.     // 12 is the number of samples in our post-process pass, so we don't want 
  734.     // pixel velocity of more than 12 pixels or else we'll see artifacts
  735.     float fVelocityCapInPixels = 3.0f;
  736.     float fVelocityCapNonHomogeneous = fVelocityCapInPixels * 2 / pBackBufferSurfaceDesc->Width;
  737.     float fVelocityCapSqNonHomogeneous = fVelocityCapNonHomogeneous * fVelocityCapNonHomogeneous;
  738.  
  739.     V_RETURN( g_pEffect->SetFloat("VelocityCapSq", fVelocityCapSqNonHomogeneous ) );
  740.     V_RETURN( g_pEffect->SetFloat("ConvertToNonHomogeneous", 1.0f / pBackBufferSurfaceDesc->Width ) );
  741.  
  742.     // Determine the technique to use when rendering world based on # of passes.
  743.     if( 1 == g_nPasses )
  744.         g_hTechWorldWithVelocity = g_pEffect->GetTechniqueByName("WorldWithVelocityMRT");
  745.     else
  746.         g_hTechWorldWithVelocity = g_pEffect->GetTechniqueByName("WorldWithVelocityTwoPasses");
  747.  
  748.     g_hPostProcessMotionBlur     = g_pEffect->GetTechniqueByName("PostProcessMotionBlur");
  749.     g_hWorld                     = g_pEffect->GetParameterByName( NULL, "mWorld" );
  750.     g_hWorldLast                 = g_pEffect->GetParameterByName( NULL, "mWorldLast" );
  751.     g_hWorldViewProjection       = g_pEffect->GetParameterByName( NULL, "mWorldViewProjection" );
  752.     g_hWorldViewProjectionLast   = g_pEffect->GetParameterByName( NULL, "mWorldViewProjectionLast" );
  753.     g_hMeshTexture               = g_pEffect->GetParameterByName( NULL, "MeshTexture" );
  754.     g_hCurFrameVelocityTexture   = g_pEffect->GetParameterByName( NULL, "CurFrameVelocityTexture" );
  755.     g_hLastFrameVelocityTexture  = g_pEffect->GetParameterByName( NULL, "LastFrameVelocityTexture" );
  756.  
  757.     // Turn off lighting since its done in the shaders 
  758.     V_RETURN( pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE ) );
  759.  
  760.     // Save a pointer to the orignal render target to restore it later
  761.     LPDIRECT3DSURFACE9 pOriginalRenderTarget;
  762.     V_RETURN( pd3dDevice->GetRenderTarget( 0, &pOriginalRenderTarget ) );
  763.  
  764.     // Clear each RT
  765.     V_RETURN( pd3dDevice->SetRenderTarget( 0, g_pFullScreenRenderTargetSurf ) );
  766.     V_RETURN( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0) );
  767.     V_RETURN( pd3dDevice->SetRenderTarget( 0, g_pLastFrameVelocitySurf ) );
  768.     V_RETURN( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0) );
  769.     V_RETURN( pd3dDevice->SetRenderTarget( 0, g_pCurFrameVelocitySurf ) );
  770.     V_RETURN( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0) );
  771.  
  772.     // Restore the orignal RT
  773.     V_RETURN( pd3dDevice->SetRenderTarget( 0, pOriginalRenderTarget ) );
  774.     SAFE_RELEASE( pOriginalRenderTarget );
  775.  
  776.     return S_OK;
  777. }
  778.  
  779.  
  780. //-----------------------------------------------------------------------------
  781. // Name: SetupFullscreenQuad()
  782. // Desc: Sets up a full screen quad.  First we render to a fullscreen render 
  783. //       target texture, and then we render that texture using this quad to 
  784. //       apply a pixel shader on every pixel of the scene.
  785. //-----------------------------------------------------------------------------
  786. void SetupFullscreenQuad( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  787. {
  788.     D3DSURFACE_DESC desc;
  789.  
  790.     g_pFullScreenRenderTargetSurf->GetDesc(&desc);
  791.  
  792.     // Ensure that we're directly mapping texels to pixels by offset by 0.5
  793.     // For more info see the doc page titled "Directly Mapping Texels to Pixels"
  794.     FLOAT fWidth5 = (FLOAT)pBackBufferSurfaceDesc->Width - 0.5f;
  795.     FLOAT fHeight5 = (FLOAT)pBackBufferSurfaceDesc->Height - 0.5f;
  796.  
  797.     FLOAT fTexWidth1 = (FLOAT)pBackBufferSurfaceDesc->Width / (FLOAT)desc.Width;
  798.     FLOAT fTexHeight1 = (FLOAT)pBackBufferSurfaceDesc->Height / (FLOAT)desc.Height;
  799.  
  800.     // Fill in the vertex values
  801.     g_Vertex[0].pos = D3DXVECTOR4(fWidth5, -0.5f, 0.0f, 1.0f);
  802.     g_Vertex[0].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  803.     g_Vertex[0].tex1 = D3DXVECTOR2(fTexWidth1, 0.0f);
  804.  
  805.     g_Vertex[1].pos = D3DXVECTOR4(fWidth5, fHeight5, 0.0f, 1.0f);
  806.     g_Vertex[1].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  807.     g_Vertex[1].tex1 = D3DXVECTOR2(fTexWidth1, fTexHeight1);
  808.  
  809.     g_Vertex[2].pos = D3DXVECTOR4(-0.5f, -0.5f, 0.0f, 1.0f);
  810.     g_Vertex[2].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  811.     g_Vertex[2].tex1 = D3DXVECTOR2(0.0f, 0.0f);
  812.  
  813.     g_Vertex[3].pos = D3DXVECTOR4(-0.5f, fHeight5, 0.0f, 1.0f);
  814.     g_Vertex[3].clr = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.66666f);
  815.     g_Vertex[3].tex1 = D3DXVECTOR2(0.0f, fTexHeight1);
  816. }
  817.  
  818.  
  819. //--------------------------------------------------------------------------------------
  820. // This callback function will be called once at the beginning of every frame. This is the
  821. // best location for your application to handle updates to the scene, but is not 
  822. // intended to contain actual rendering calls, which should instead be placed in the 
  823. // OnFrameRender callback.  
  824. //--------------------------------------------------------------------------------------
  825. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double dTime, float fElapsedTime )
  826. {
  827.     float fTime = (float)dTime;
  828.  
  829.     // Update the camera's postion based on user input 
  830.     g_Camera.FrameMove( fElapsedTime );
  831.  
  832.     if( g_nCurrentScene == 1 )
  833.     {
  834.         // Move the objects around based on some simple function
  835.         int iObject;
  836.         for( iObject=0; iObject < NUM_OBJECTS; iObject++ )
  837.         {
  838.             D3DXVECTOR3 vPos;
  839.  
  840.             float fRadius = 7.0f;
  841.             if( iObject >= 30 && iObject < 41 )
  842.             {
  843.                 vPos.x = cosf(g_fObjectSpeed*0.125f*fTime + 2*D3DX_PI/10*(iObject-30)) * fRadius;
  844.                 vPos.y = 10.0f;
  845.                 vPos.z = sinf(g_fObjectSpeed*0.125f*fTime + 2*D3DX_PI/10*(iObject-30)) * fRadius - 25.0f;
  846.             }
  847.             else if( iObject >= 20 && iObject < 31 )
  848.             {
  849.                 vPos.x = cosf(g_fObjectSpeed*0.25f*fTime + 2*D3DX_PI/10*(iObject-20)) * fRadius;
  850.                 vPos.y = 10.0f;
  851.                 vPos.z = sinf(g_fObjectSpeed*0.25f*fTime + 2*D3DX_PI/10*(iObject-20)) * fRadius - 5.0f;
  852.             }
  853.             else if( iObject >= 10 && iObject < 21 )
  854.             {
  855.                 vPos.x = cosf(g_fObjectSpeed*0.5f*fTime + 2*D3DX_PI/10*(iObject-10)) * fRadius;
  856.                 vPos.y = 0.0f;
  857.                 vPos.z = sinf(g_fObjectSpeed*0.5f*fTime + 2*D3DX_PI/10*(iObject-10)) * fRadius - 25.0f;
  858.             }
  859.             else
  860.             {
  861.                 vPos.x = cosf(g_fObjectSpeed*fTime + 2*D3DX_PI/10*iObject) * fRadius;
  862.                 vPos.y = 0.0f;
  863.                 vPos.z = sinf(g_fObjectSpeed*fTime + 2*D3DX_PI/10*iObject) * fRadius - 5.0f;
  864.             }
  865.  
  866.             g_pScene1Object[iObject]->g_vWorldPos = vPos;
  867.  
  868.             // Store the last world matrix so that we can tell the effect file
  869.             // what it was when we render this object
  870.             g_pScene1Object[iObject]->g_mWorldLast = g_pScene1Object[iObject]->g_mWorld;
  871.  
  872.             // Update the current world matrix for this object
  873.             D3DXMatrixTranslation( &g_pScene1Object[iObject]->g_mWorld, g_pScene1Object[iObject]->g_vWorldPos.x, g_pScene1Object[iObject]->g_vWorldPos.y, g_pScene1Object[iObject]->g_vWorldPos.z );
  874.         }
  875.     }
  876.  
  877.     if( g_nSleepTime > 0 )
  878.         Sleep(g_nSleepTime);
  879. }
  880.  
  881.  
  882. //--------------------------------------------------------------------------------------
  883. // This callback function will be called at the end of every frame to perform all the 
  884. // rendering calls for the scene, and it will also be called if the window needs to be 
  885. // repainted. After this function has returned, the sample framework will call 
  886. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  887. //--------------------------------------------------------------------------------------
  888. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  889. {
  890.     HRESULT hr;
  891.     LPDIRECT3DSURFACE9 apOriginalRenderTarget[2] = { NULL, NULL };
  892.     D3DXMATRIXA16 mProj;
  893.     D3DXMATRIXA16 mView;
  894.     D3DXMATRIXA16 mViewProjection;
  895.     D3DXMATRIXA16 mWorldViewProjection;
  896.     D3DXMATRIXA16 mWorldViewProjectionLast;
  897.     D3DXMATRIXA16 mWorld;
  898.     D3DXVECTOR4 vEyePt;
  899.     UINT iPass, cPasses;
  900.            
  901.     // Swap the current frame's per-pixel velocity texture with  
  902.     // last frame's per-pixel velocity texture
  903.     LPDIRECT3DTEXTURE9 pTempTex = g_pCurFrameVelocityTexture;
  904.     g_pCurFrameVelocityTexture = g_pLastFrameVelocityTexture;
  905.     g_pLastFrameVelocityTexture = pTempTex;
  906.  
  907.     LPDIRECT3DSURFACE9 pTempSurf = g_pCurFrameVelocitySurf;
  908.     g_pCurFrameVelocitySurf = g_pLastFrameVelocitySurf;
  909.     g_pLastFrameVelocitySurf = pTempSurf;
  910.  
  911.     CRenderTargetSet *pTempRTSet = g_pCurFrameRTSet;
  912.     g_pCurFrameRTSet = g_pLastFrameRTSet;
  913.     g_pLastFrameRTSet = pTempRTSet;
  914.  
  915.     // Save a pointer to the current render target in the swap chain
  916.     V( pd3dDevice->GetRenderTarget( 0, &apOriginalRenderTarget[0] ) );
  917.  
  918.     V( g_pEffect->SetFloat("PixelBlurConst", g_fPixelBlurConst) );
  919.  
  920.     V( g_pEffect->SetTexture( g_hCurFrameVelocityTexture, g_pCurFrameVelocityTexture) );
  921.     V( g_pEffect->SetTexture( g_hLastFrameVelocityTexture, g_pLastFrameVelocityTexture) );
  922.  
  923.     // Clear the velocity render target to 0
  924.     V( pd3dDevice->SetRenderTarget( 0, g_pCurFrameVelocitySurf ) );
  925.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0) );
  926.  
  927.     // Clear the full screen render target to the background color
  928.     V( pd3dDevice->SetRenderTarget( 0, g_pFullScreenRenderTargetSurf ) );
  929.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, g_dwBackgroundColor, 1.0f, 0) );
  930.  
  931.     // Turn on Z for this pass
  932.     V( pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE) );
  933.  
  934.     // For the first pass we'll draw the screen to the full screen render target
  935.     // and to update the velocity render target with the velocity of each pixel
  936.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  937.     {
  938.         // Set world drawing technique
  939.         V( g_pEffect->SetTechnique( g_hTechWorldWithVelocity ) );
  940.     
  941.         // Get the projection & view matrix from the camera class
  942.         mProj = *g_Camera.GetProjMatrix();       
  943.         mView = *g_Camera.GetViewMatrix();
  944.     
  945.         mViewProjection = mView * mProj;
  946.     
  947.         if( g_nCurrentScene == 1 )
  948.         {
  949.             // For each object, tell the effect about the object's current world matrix
  950.             // and its last frame's world matrix and render the object. 
  951.             // The vertex shader can then use both these matricies to calculate how 
  952.             // much each vertex has moved.  The pixel shader then interpolates this 
  953.             // vertex velocity for each pixel
  954.             for( int iObject=0; iObject < NUM_OBJECTS; iObject++ )
  955.             {
  956.                 mWorldViewProjection = g_pScene1Object[iObject]->g_mWorld * mViewProjection;
  957.                 mWorldViewProjectionLast = g_pScene1Object[iObject]->g_mWorldLast * g_mViewProjectionLast;
  958.     
  959.                 // Tell the effect where the camera is now
  960.                 V( g_pEffect->SetMatrix( g_hWorldViewProjection, &mWorldViewProjection) );
  961.                 V( g_pEffect->SetMatrix( g_hWorld, &g_pScene1Object[iObject]->g_mWorld ) );
  962.     
  963.                 // Tell the effect where the camera was last frame
  964.                 V( g_pEffect->SetMatrix( g_hWorldViewProjectionLast, &mWorldViewProjectionLast) );
  965.     
  966.                 // Tell the effect the current mesh's texture
  967.                 V( g_pEffect->SetTexture( g_hMeshTexture, g_pScene1Object[iObject]->g_pMeshTexture) );
  968.     
  969.                 V( g_pEffect->Begin(&cPasses, 0) );
  970.                 for (iPass = 0; iPass < cPasses; iPass++)
  971.                 {
  972.                     // Set the render targets here.  If multiple render targets are
  973.                     // supported, render target 1 is set to be the velocity surface.
  974.                     // If multiple render targets are not supported, the velocity
  975.                     // surface will be rendered in the 2nd pass.
  976.                     for( int rt = 0; rt < g_nRtUsed; ++rt )
  977.                         V( pd3dDevice->SetRenderTarget( rt, g_pCurFrameRTSet->pRT[iPass][rt] ) );
  978.  
  979.                     V( g_pEffect->BeginPass(iPass) );
  980.                     V( g_pScene1Object[iObject]->g_pMesh->DrawSubset(0) );
  981.                     V( g_pEffect->EndPass() );
  982.                 }
  983.                 V( g_pEffect->End() );
  984.             }
  985.         }
  986.         else if( g_nCurrentScene == 2 )
  987.         {
  988.             for( int iObject=0; iObject < NUM_WALLS; iObject++ )
  989.             {
  990.                 mWorldViewProjection = g_pScene2Object[iObject]->g_mWorld * mViewProjection;
  991.                 mWorldViewProjectionLast = g_pScene2Object[iObject]->g_mWorldLast * g_mViewProjectionLast;
  992.     
  993.                 // Tell the effect where the camera is now
  994.                 V( g_pEffect->SetMatrix( g_hWorldViewProjection, &mWorldViewProjection) );
  995.                 V( g_pEffect->SetMatrix( g_hWorld, &g_pScene2Object[iObject]->g_mWorld ) );
  996.     
  997.                 // Tell the effect where the camera was last frame
  998.                 V( g_pEffect->SetMatrix( g_hWorldViewProjectionLast, &mWorldViewProjectionLast) );
  999.     
  1000.                 // Tell the effect the current mesh's texture
  1001.                 V( g_pEffect->SetTexture( g_hMeshTexture, g_pScene2Object[iObject]->g_pMeshTexture) );
  1002.     
  1003.                 V( g_pEffect->Begin(&cPasses, 0) );
  1004.                 for (iPass = 0; iPass < cPasses; iPass++)
  1005.                 {
  1006.                     // Set the render targets here.  If multiple render targets are
  1007.                     // supported, render target 1 is set to be the velocity surface.
  1008.                     // If multiple render targets are not supported, the velocity
  1009.                     // surface will be rendered in the 2nd pass.
  1010.                     for( int rt = 0; rt < g_nRtUsed; ++rt )
  1011.                         V( pd3dDevice->SetRenderTarget( rt, g_pCurFrameRTSet->pRT[iPass][rt] ) );
  1012.  
  1013.                     V( g_pEffect->BeginPass(iPass) );
  1014.                     V( g_pScene2Object[iObject]->g_pMesh->DrawSubset(0) );
  1015.                     V( g_pEffect->EndPass() );
  1016.                 }
  1017.                 V( g_pEffect->End() );
  1018.             }
  1019.         }
  1020.     
  1021.         V( pd3dDevice->EndScene() );
  1022.     }
  1023.  
  1024.     // Remember the current view projection matrix for next frame
  1025.     g_mViewProjectionLast = mViewProjection;
  1026.  
  1027.     // Now that we have the scene rendered into g_pFullScreenRenderTargetSurf
  1028.     // and the pixel velocity rendered into g_pCurFrameVelocitySurf 
  1029.     // we can do a final pass to render this into the backbuffer and use
  1030.     // a pixel shader to blur the pixels based on the last frame's & current frame's 
  1031.     // per pixel velocity to achieve a motion blur effect
  1032.     for( int rt = 0; rt < g_nRtUsed; ++rt )
  1033.         V( pd3dDevice->SetRenderTarget( rt, apOriginalRenderTarget[rt] ) );
  1034.     SAFE_RELEASE( apOriginalRenderTarget[0] );
  1035.     V( pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE) );
  1036.  
  1037.     // Clear the render target
  1038.     V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0L ) );
  1039.  
  1040.     // Above we rendered to a fullscreen render target texture, and now we 
  1041.     // render that texture using a quad to apply a pixel shader on every pixel of the scene.
  1042.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  1043.     {
  1044.         V( g_pEffect->SetTechnique( g_hPostProcessMotionBlur ) );
  1045.  
  1046.         V( g_pEffect->Begin(&cPasses, 0) );
  1047.         for (iPass = 0; iPass < cPasses; iPass++)
  1048.         {
  1049.             V( g_pEffect->BeginPass(iPass) );
  1050.             V( pd3dDevice->SetFVF(SCREEN_VERTEX::FVF) );
  1051.             V( pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Vertex, sizeof(SCREEN_VERTEX)) );
  1052.             V( g_pEffect->EndPass() );
  1053.         }
  1054.         V( g_pEffect->End() );
  1055.  
  1056.         V( g_HUD.OnRender( fElapsedTime ) );
  1057.         V( g_SampleUI.OnRender( fElapsedTime ) );
  1058.         RenderText();
  1059.  
  1060.         V( pd3dDevice->EndScene() );
  1061.     }
  1062. }
  1063.  
  1064.  
  1065. //--------------------------------------------------------------------------------------
  1066. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  1067. // efficient text rendering.
  1068. //--------------------------------------------------------------------------------------
  1069. void RenderText()
  1070. {
  1071.     // The helper object simply helps keep track of text position, and color
  1072.     // and then it calls pFont->DrawText( g_pSprite, strMsg, -1, &rc, DT_NOCLIP, g_clr );
  1073.     // If NULL is passed in as the sprite object, then it will work however the 
  1074.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  1075.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  1076.  
  1077.     // Output statistics
  1078.     txtHelper.Begin();
  1079.     txtHelper.SetInsertionPos( 5, 5 );
  1080.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  1081.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  1082.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  1083.  
  1084.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  1085.     txtHelper.DrawFormattedTextLine( L"Blur=%0.2f Object Speed=%0.1f Camera Speed=%0.1f", g_fPixelBlurConst, g_fObjectSpeed, g_fCameraSpeed );
  1086.  
  1087.     if( g_nSleepTime == 0 )
  1088.         txtHelper.DrawTextLine( L"Not sleeping between frames" );
  1089.     else
  1090.         txtHelper.DrawFormattedTextLine( L"Sleeping %dms per frame", g_nSleepTime );
  1091.  
  1092.     // Draw help
  1093.     if( g_bShowHelp )
  1094.     {
  1095.         const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc();
  1096.         txtHelper.SetInsertionPos( 10, pd3dsdBackBuffer->Height-15*6 );
  1097.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 0.75f, 0.0f, 1.0f ) );
  1098.         txtHelper.DrawTextLine( L"Controls (F1 to hide):" );
  1099.  
  1100.         txtHelper.SetInsertionPos( 40, pd3dsdBackBuffer->Height-15*5 );
  1101.         txtHelper.DrawTextLine( L"Look: Left drag mouse\n"
  1102.                                 L"Move: A,W,S,D or Arrow Keys\n"
  1103.                                 L"Move up/down: Q,E or PgUp,PgDn\n"
  1104.                                 L"Reset camera: Home\n"
  1105.                                 L"Quit: ESC" );
  1106.     }
  1107.     else
  1108.     {
  1109.         txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  1110.         txtHelper.DrawTextLine( L"Press F1 for help" );
  1111.     }
  1112.     txtHelper.End();
  1113. }
  1114.  
  1115.  
  1116. //--------------------------------------------------------------------------------------
  1117. // Before handling window messages, the sample framework passes incoming windows 
  1118. // messages to the application through this callback function. If the application sets 
  1119. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  1120. //--------------------------------------------------------------------------------------
  1121. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  1122. {
  1123.     // Give the dialogs a chance to handle the message first
  1124.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  1125.     if( *pbNoFurtherProcessing )
  1126.         return 0;
  1127.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  1128.     if( *pbNoFurtherProcessing )
  1129.         return 0;
  1130.  
  1131.     // Pass all remaining windows messages to camera so it can respond to user input
  1132.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  1133.  
  1134.     return 0;
  1135. }
  1136.  
  1137.  
  1138. //--------------------------------------------------------------------------------------
  1139. // As a convenience, the sample framework inspects the incoming windows messages for
  1140. // keystroke messages and decodes the message parameters to pass relevant keyboard
  1141. // messages to the application.  The framework does not remove the underlying keystroke 
  1142. // messages, which are still passed to the application's MsgProc callback.
  1143. //--------------------------------------------------------------------------------------
  1144. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  1145. {
  1146.     if( bKeyDown )
  1147.     {
  1148.         switch( nChar )
  1149.         {
  1150.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  1151.         }
  1152.     }
  1153. }
  1154.  
  1155.  
  1156. //--------------------------------------------------------------------------------------
  1157. // Handles the GUI events
  1158. //--------------------------------------------------------------------------------------
  1159. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  1160. {
  1161.     switch( nControlID )
  1162.     {
  1163.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  1164.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  1165.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  1166.  
  1167.         case IDC_CHANGE_SCENE:
  1168.         {
  1169.             g_nCurrentScene %= 2;
  1170.             g_nCurrentScene++;
  1171.  
  1172.             switch( g_nCurrentScene )
  1173.             {
  1174.                 case 1:
  1175.                 {
  1176.                     D3DXVECTOR3 vecEye(40.0f, 0.0f, -15.0f);
  1177.                     D3DXVECTOR3 vecAt (4.0f, 4.0f, -15.0f);
  1178.                     g_Camera.SetViewParams( &vecEye, &vecAt );
  1179.                     break;
  1180.                 }
  1181.  
  1182.                 case 2:
  1183.                 {
  1184.                     D3DXVECTOR3 vecEye(0.125f, 1.25f, 3.0f);
  1185.                     D3DXVECTOR3 vecAt (0.125f, 1.25f, 4.0f);
  1186.                     g_Camera.SetViewParams( &vecEye, &vecAt );
  1187.                     break;
  1188.                 }
  1189.             }
  1190.             break;
  1191.         }
  1192.  
  1193.         case IDC_ENABLE_BLUR:
  1194.         {
  1195.             static float s_fRemember = 1.0f;
  1196.             if( g_SampleUI.GetCheckBox( IDC_ENABLE_BLUR )->GetChecked() )
  1197.             {
  1198.                 g_fPixelBlurConst = s_fRemember;
  1199.                 g_SampleUI.GetStatic( IDC_BLUR_FACTOR_STATIC )->SetEnabled( true );
  1200.                 g_SampleUI.GetSlider( IDC_BLUR_FACTOR )->SetEnabled( true );
  1201.             }
  1202.             else
  1203.             {
  1204.                 s_fRemember = g_fPixelBlurConst;
  1205.                 g_fPixelBlurConst = 0.0f;
  1206.                 g_SampleUI.GetStatic( IDC_BLUR_FACTOR_STATIC )->SetEnabled( false );
  1207.                 g_SampleUI.GetSlider( IDC_BLUR_FACTOR )->SetEnabled( false );
  1208.             }
  1209.             break;
  1210.         }
  1211.  
  1212.         case IDC_FRAMERATE:
  1213.         {
  1214.             WCHAR sz[100];
  1215.             g_nSleepTime = g_SampleUI.GetSlider( IDC_FRAMERATE )->GetValue();
  1216.             _snwprintf( sz, 100, L"Sleep: %dms/frame", g_nSleepTime ); sz[99] = 0;
  1217.             g_SampleUI.GetStatic( IDC_FRAMERATE_STATIC )->SetText( sz );
  1218.             break;
  1219.         }
  1220.  
  1221.         case IDC_BLUR_FACTOR:
  1222.         {
  1223.             WCHAR sz[100];
  1224.             g_fPixelBlurConst = (float)g_SampleUI.GetSlider( IDC_BLUR_FACTOR )->GetValue() / 100.0f;
  1225.             _snwprintf( sz, 100, L"Blur Factor: %0.2f", g_fPixelBlurConst ); sz[99] = 0;
  1226.             g_SampleUI.GetStatic( IDC_BLUR_FACTOR_STATIC )->SetText( sz );
  1227.             break;
  1228.         }
  1229.  
  1230.         case IDC_OBJECT_SPEED:
  1231.         {  
  1232.             WCHAR sz[100];
  1233.             g_fObjectSpeed = (float)g_SampleUI.GetSlider( IDC_OBJECT_SPEED )->GetValue();
  1234.             _snwprintf( sz, 100, L"Object Speed: %0.2f", g_fObjectSpeed ); sz[99] = 0;
  1235.             g_SampleUI.GetStatic( IDC_OBJECT_SPEED_STATIC )->SetText( sz );
  1236.             break;
  1237.         }
  1238.  
  1239.         case IDC_CAMERA_SPEED:
  1240.         { 
  1241.             WCHAR sz[100];
  1242.             g_fCameraSpeed = (float)g_SampleUI.GetSlider( IDC_CAMERA_SPEED )->GetValue();
  1243.             _snwprintf( sz, 100, L"Camera Speed: %0.2f", g_fCameraSpeed ); sz[99] = 0;
  1244.             g_SampleUI.GetStatic( IDC_CAMERA_SPEED_STATIC )->SetText( sz );
  1245.             g_Camera.SetScalers( 0.01f, g_fCameraSpeed );
  1246.             break;
  1247.         }
  1248.     }
  1249. }
  1250.  
  1251.  
  1252. //--------------------------------------------------------------------------------------
  1253. // This callback function will be called immediately after the Direct3D device has 
  1254. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  1255. // in the OnResetDevice callback should be released here, which generally includes all 
  1256. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  1257. // information about lost devices.
  1258. //--------------------------------------------------------------------------------------
  1259. void CALLBACK OnLostDevice()
  1260. {
  1261.     if( g_pFont )
  1262.         g_pFont->OnLostDevice();
  1263.     if( g_pEffect )
  1264.         g_pEffect->OnLostDevice();
  1265.     SAFE_RELEASE(g_pTextSprite);
  1266.     SAFE_RELEASE(g_pFullScreenRenderTargetSurf);
  1267.     SAFE_RELEASE(g_pFullScreenRenderTarget);
  1268.     SAFE_RELEASE(g_pPixelVelocitySurf1);
  1269.     SAFE_RELEASE(g_pPixelVelocityTexture1);
  1270.     SAFE_RELEASE(g_pPixelVelocitySurf2);
  1271.     SAFE_RELEASE(g_pPixelVelocityTexture2);
  1272. }
  1273.  
  1274.  
  1275. //--------------------------------------------------------------------------------------
  1276. // This callback function will be called immediately after the Direct3D device has 
  1277. // been destroyed, which generally happens as a result of application termination or 
  1278. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  1279. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  1280. //--------------------------------------------------------------------------------------
  1281. void CALLBACK OnDestroyDevice()
  1282. {
  1283.     SAFE_RELEASE(g_pEffect);
  1284.     SAFE_RELEASE(g_pFont);
  1285.  
  1286.     SAFE_RELEASE(g_pFullScreenRenderTargetSurf);
  1287.     SAFE_RELEASE(g_pFullScreenRenderTarget);
  1288.  
  1289.     SAFE_RELEASE(g_pMesh1);
  1290.     SAFE_RELEASE(g_pMeshTexture1);
  1291.     SAFE_RELEASE(g_pMesh2);
  1292.     SAFE_RELEASE(g_pMeshTexture2);
  1293.     SAFE_RELEASE(g_pMeshTexture3);
  1294. }
  1295.  
  1296.  
  1297.  
  1298.